package biz.datalk.industrialland.common.encrypt;

import biz.datalk.industrialland.common.encrypt.exception.RSAException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.xml.bind.DatatypeConverter;
import java.io.ByteArrayOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * RSA公钥/私钥/签名工具包
 * <p>
 * 罗纳德·李维斯特（Ron [R]ivest）、阿迪·萨莫尔（Adi [S]hamir）和伦纳德·阿德曼（Leonard [A]dleman）
 * <p>
 * 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>
 * 由于非对称加密速度极其缓慢，一般文件不使用它来加密而是使用对称加密，<br/>
 * 非对称加密算法可以用来对对称加密的密钥加密，这样保证密钥的安全也就保证了数据的安全
 *
 * @date 2019-08-25
 */
@Slf4j
public class RSATool {

    /** 加密算法 RSA */
    private static final String ALGORITHM = "RSA";

    /** 签名算法 */
    private static final String SIGNATURE_ALGORITHM = "MD5withRSA";

    /** 获取公钥的key */
    private static final String PUBLIC_KEY = "RSAPublicKey";

    /** 获取私钥的key */
    private static final String PRIVATE_KEY = "RSAPrivateKey";

    /** RSA最大加密明文大小 */
    private static final int MAX_ENCRYPT_BLOCK = 117;

    /** RSA最大解密密文大小 */
    private static final int MAX_DECRYPT_BLOCK = 128;

    /** RSA 位数 如果采用2048 上面最大加密和最大解密则须填写:  245 256 */
    private static final int INITIALIZE_LENGTH = 1024;

    /**
     * 生成密钥对(公钥和私钥)
     *
     * @return 密钥对
     *
     * @throws RSAException 算法指定错误时抛出；生成key发生异常时抛出
     */
    public static KeyPair getkeyPair() throws RSAException {
        try {
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM);
            keyPairGen.initialize(INITIALIZE_LENGTH);
            return keyPairGen.generateKeyPair();
        } catch (Exception ex) {
            log.error("{}", ex.getMessage(), ex);
            throw new RSAException(ex);
        }
    }

    /**
     * 生成密钥对(公钥和私钥)
     *
     * @return 密钥对
     *
     * @throws RSAException
     */
    public static Map<String, Object> genKeyPair() throws RSAException {
        KeyPair keyPair = getkeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }

    /**
     * 用私钥对信息生成数字签名
     *
     * @param data       已加密数据
     * @param privateKey 私钥(BASE64编码)
     *
     * @return 数字签名
     *
     * @throws RSAException
     */
    public static String sign(byte[] data, String privateKey) throws RSAException {
        try {
            byte[] keyBytes = Base64.decodeBase64(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initSign(privateK);
            signature.update(data);
            return Base64.encodeBase64String(signature.sign());
        } catch (Exception ex) {
            log.error("{}", ex.getMessage(), ex);
            throw new RSAException(ex);
        }
    }

    /**
     * 校验数字签名
     *
     * @param data      已加密数据
     * @param publicKey 公钥(BASE64编码)
     * @param sign      数字签名
     *
     * @return true-签名合法 否则签名不合法
     *
     * @throws RSAException
     */
    public static boolean verify(byte[] data, String publicKey, String sign) throws RSAException {
        try {
            byte[] keyBytes = Base64.decodeBase64(publicKey);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            PublicKey pk = keyFactory.generatePublic(keySpec);
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initVerify(pk);
            signature.update(data);
            return signature.verify(Base64.decodeBase64(sign));
        } catch (Exception ex) {
            log.error("{}", ex.getMessage(), ex);
            throw new RSAException(ex);
        }
    }

    /**
     * 私钥解密
     *
     * @param encryptedData 已加密数据
     * @param privateKey    私钥(BASE64编码)
     *
     * @return 解密后的明文
     *
     * @throws RSAException
     */
    public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws RSAException {
        ByteArrayOutputStream out = null;
        try {
            byte[] keyBytes = Base64.decodeBase64(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            Key pk = keyFactory.generatePrivate(pkcs8KeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, pk);
            int inputLen = encryptedData.length;
            out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.flush();
            return decryptedData;
        } catch (Exception ex) {
            log.error("{}", ex.getMessage(), ex);
            throw new RSAException(ex);
        } finally {
            close(out);
        }
    }

    /**
     * 公钥解密
     *
     * @param encryptedData 已加密数据
     * @param publicKey     公钥(BASE64编码)
     *
     * @return 解密后的明文
     *
     * @throws RSAException
     */
    public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws RSAException {
        ByteArrayOutputStream out = null;
        try {
            byte[] keyBytes = Base64.decodeBase64(publicKey);
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            Key pk = keyFactory.generatePublic(x509KeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, pk);
            int inputLen = encryptedData.length;
            out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.flush();
            return decryptedData;
        } catch (Exception ex) {
            log.error("{}", ex.getMessage(), ex);
            throw new RSAException(ex);
        } finally {
            close(out);
        }
    }

    /**
     * 公钥加密
     *
     * @param data      源数据
     * @param publicKey 公钥(BASE64编码)
     *
     * @return
     *
     * @throws RSAException
     */
    public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws RSAException {
        ByteArrayOutputStream out = null;
        try {
            byte[] keyBytes = Base64.decodeBase64(publicKey);
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            Key pk = keyFactory.generatePublic(x509KeySpec);
            // 对数据加密
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, pk);
            int inputLen = data.length;
            out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.flush();
            return encryptedData;
        } catch (Exception ex) {
            log.error("{}", ex.getMessage(), ex);
            throw new RSAException(ex);
        } finally {
            close(out);
        }
    }

    /**
     * 私钥加密
     *
     * @param data       源数据
     * @param privateKey 私钥(BASE64编码)
     *
     * @return
     *
     * @throws RSAException
     */
    public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws RSAException {
        ByteArrayOutputStream out = null;
        try {
            byte[] keyBytes = Base64.decodeBase64(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            Key pk = keyFactory.generatePrivate(pkcs8KeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, pk);
            int inputLen = data.length;
            out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.flush();
            return encryptedData;
        } catch (Exception ex) {
            log.error("{}", ex.getMessage(), ex);
            throw new RSAException(ex);
        } finally {
            close(out);
        }
    }

    private static void close(ByteArrayOutputStream out) {
        try {
            if (out != null) {
                out.close();
            }
        } catch (IOException ex) {
            throw new RSAException(ex);
        }
    }


    /**
     * 获取私钥
     *
     * @param keyMap 密钥对
     *
     * @return
     *
     * @throws RSAException
     */
    public static String getPrivateKey(Map<String, Object> keyMap) throws RSAException {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return Base64.encodeBase64String(key.getEncoded());
    }

    /**
     * 获取公钥
     *
     * @param keyMap 密钥对
     *
     * @return
     *
     * @throws RSAException
     */
    public static String getPublicKey(Map<String, Object> keyMap) throws RSAException {
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return Base64.encodeBase64String(key.getEncoded());
    }

    /**
     * java端公钥加密
     *
     * @param plantext  需要加密的明文
     * @param publickey RSA 公钥
     *
     * @return 加密后的密文
     *
     * @throws RSAException
     * @author tarofang@163.com
     * @date 2019-08-25
     */
    public static String encrypt(String plantext, String publickey) throws RSAException {
        try {
            return Base64.encodeBase64String(encryptByPublicKey(plantext.getBytes(StandardCharsets.UTF_8.name()), publickey));
        } catch (Exception ex) {
            log.error("{}", ex.getMessage(), ex);
            throw new RSAException(ex);
        }
    }

    /**
     * java端私钥解密
     *
     * @param ciphertext 需要解密的密文
     * @param privatekey RSA 私钥
     *
     * @return 解密后的明文
     *
     * @throws RSAException
     * @author tarofang@163.com
     * @date 2019-08-25
     */
    public static String decrypt(String ciphertext, String privatekey) throws RSAException {
        try {
            return new String(decryptByPrivateKey(Base64.decodeBase64(ciphertext), privatekey), StandardCharsets.UTF_8.name());
        } catch (Exception ex) {
            log.error("{}", ex.getMessage(), ex);
            throw new RSAException(ex);
        }
    }

    public static void main(String[] args) throws Exception {

        // String startLine = "-----BEGIN CERTIFICATE-----\n";
        // String endLine = "\n-----END CERTIFICATE-----\n";
        String startLine = "-----BEGIN PUBLIC KEY-----\n";
        String endLine = "\n-----END PUBLIC KEY-----\n";
        String serverPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCcneJM34g4Cw9Qg7va56JMKfSEN8uYyyUkFiGPG8HaynMYXkiaYI+/uVDOrd+4INbEyR7R+gHyXTna1qebPcT8uaoz6+ftXAH26MsI5XBPaHJRrET6ZDOFdXhhpBka6NfstGeoz7mCnT2CEZuk+fBvBTyamjo+lYWuWvAm2MasEQIDAQAB";
        String clientPrivateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJGBH7NDV2mU5ro88K0CEJ75gXVxxPzHGUHzTdpVt9b8bWPfjAJv9c1MQ9qvOHIkVCylmVfrbEwGCIArUx3osMPkQEWulH9MaxS2PDShaz+mYzqwcV4DGzJAWK4ePmpFXFrxk63jIFLM6Lj5Quq1H7ePTZAEHIU98OQ0VttNX3zhAgMBAAECgYBj04YPNB1tt5XQomyxFeCXYTD7hZGTp3lhsO5x5Ctb2RWn1sA1D+FA95j6GQsN7HS/qOGa208SnXUJki/VLkbPJLaVY8EpBvtbx/MjmH7SWqH1jZeN6pTA4HEw56fRDY/VyjxOrEPE9zNRK4sYoyv8rrstPD1aaf2bTZ4ShnXFjQJBANX2BHLyFliL9sYUIvYmMfG/5LG0A3RUU0itNItrIB/4ck2y5IQxLwkr6YAVfPtFuA9xiLGIhs7mbO2BFS7XnDcCQQCuF9IR24jo6jiDkbc+7huePNyq6xZZFSkgBoTQQrP8xGyVIZR391wjBgWeuCbD9ylNobFF9TJM20gZN03Po5OnAkBp/VoM2vHI4WTYkMcU6qzZFfcjNIp1iQRMv0iFPAcI71koNlNPTNIBGBiuk3Z7PvlD5TkSwRAO1ETnjodA0hwXAkEAggf8uaXVztISwAK4ceJ68mfXEjphCMyLWQZFcSBBO0yjJYhdUnWJdgdrby9wlPIpAXkB5ZTMqycl5N+v2KT/BQJBALpCgJAbtdupZFhXg+lYJJ6ZnwNosCEwRlmczOG+KdoF2x88t6k37aOybiBFq750R0zDKxwoafulvPh6pQuF3wI=";
        String clientPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCRgR+zQ1dplOa6PPCtAhCe+YF1ccT8xxlB803aVbfW/G1j34wCb/XNTEParzhyJFQspZlX62xMBgiAK1Md6LDD5EBFrpR/TGsUtjw0oWs/pmM6sHFeAxsyQFiuHj5qRVxa8ZOt4yBSzOi4+ULqtR+3j02QBByFPfDkNFbbTV984QIDAQAB";

        String serverPubKeyPath = "/Users/tarofang/Downloads/baidu_wangpan/serverPubKey.txt";
        byte[] serverPublicKeyBytes = Base64.decodeBase64(serverPublicKey);
        X509EncodedKeySpec serverPubKeySpec = new X509EncodedKeySpec(serverPublicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        RSAPublicKey serverPubKey = (RSAPublicKey) keyFactory.generatePublic(serverPubKeySpec);
        StringWriter sw = new StringWriter();
        String s = DatatypeConverter.printBase64Binary(serverPubKey.getEncoded()).replaceAll("(.{64})", "$1\n");
        System.out.println("serverPubKeyPath===>\n" + s + "\n");
        sw.write(startLine);
        sw.write(s);
        sw.write(endLine);
        try (FileWriter fw = new FileWriter(serverPubKeyPath)) {
            fw.write(sw.toString());
        }

        String clientPubKeyPath = "/Users/tarofang/Downloads/baidu_wangpan/clientPubKey.txt";
        byte[] clientPublicKeyBytes = Base64.decodeBase64(clientPublicKey);
        X509EncodedKeySpec clientPubKeySpec = new X509EncodedKeySpec(clientPublicKeyBytes);
        KeyFactory keyFactory2 = KeyFactory.getInstance(ALGORITHM);
        RSAPublicKey clientPubKey = (RSAPublicKey) keyFactory2.generatePublic(clientPubKeySpec);
        sw = new StringWriter();
        s = DatatypeConverter.printBase64Binary(clientPubKey.getEncoded()).replaceAll("(.{64})", "$1\n");
        System.out.println("clientPubKey===>\n" + s + "\n");
        sw.write(startLine);
        sw.write(s);
        sw.write(endLine);
        try (FileWriter fw = new FileWriter(clientPubKeyPath)) {
            fw.write(sw.toString());
        }

        String clientPriKeyPath = "/Users/tarofang/Downloads/baidu_wangpan/clientPriKey.txt";
        byte[] clientPrivateKeyBytes = Base64.decodeBase64(clientPrivateKey);
        PKCS8EncodedKeySpec clientPrivateKeyPKCS8 = new PKCS8EncodedKeySpec(clientPrivateKeyBytes);
        KeyFactory keyFactory3 = KeyFactory.getInstance(ALGORITHM);
        RSAPrivateKey clientPriKey = (RSAPrivateKey) keyFactory3.generatePrivate(clientPrivateKeyPKCS8);
        sw = new StringWriter();
        s = DatatypeConverter.printBase64Binary(clientPriKey.getEncoded()).replaceAll("(.{64})", "$1\n");
        System.out.println("clientPriKey===>\n" + s + "\n");
        sw.write("-----BEGIN RSA PRIVATE KEY-----\n");
        sw.write(s);
        sw.write("\n-----END RSA PRIVATE KEY-----\n");
        try (FileWriter fw = new FileWriter(clientPriKeyPath)) {
            fw.write(sw.toString());
        }

        // Map<String, Object> stringObjectMap = genKeyPair();
        // System.out.println("privateKey > " + getPrivateKey(stringObjectMap));
        // System.out.println("publicKey >  " + getPublicKey(stringObjectMap));
        //
        // String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIT3+7v+JhEEq8uRx0xzPzW4swCa1z/8G6wXaA/niAkYUnI0AutRLbHWwQR8WX1NrG9EU4G7dsGNvI8sphdCGQxgZiLLCvRztA7MC2njTJnxyyrvC36J3Je5R107iNuAd8D0210UnX9D4+hdvyjL6lSTAui01jCq3LLwutVGYAsbAgMBAAECgYBzhSJ+JAIcXOuIE2GLqMBswsc5Kk0BeNztuPQehS9pf2j5cPhsSn2heIr+g64Xr6i0ji7ikeRNqf78gHTX1gP9t1XDGAl+1gnmF7a6ifjjXG977inWR/S5XSmPv6AwrkipTzgEGqEPxBbe3xIt06fLiuObrQQsewuKcuda5zheGQJBAN712s0RBZJ+ohABt3wkIA/jE/fbMakqFoT0B29yU2t7oJu8eJWX04Hv9XOXz2oKUh8iY5cnMCnfbdJp2n2MWfUCQQCYrDxwEbSA0N8GbaMhdxKYJtP4Jbyay30XRFYTPHJWEyTr2kUoMyg9GdWCgdObkmr1jRqe5occK8bEzpF7H1bPAkB2wIfrVTeckSoMUH3D9xHEpHPMPckziqE36ynSqBfaVZxzlmy7cIRM3tvi12a32gtnXc+hgFPc2Y4K1ipzWD/JAkAbr9iCBmPynG5lrwpPblWb7CaysL1EYTS9PHJTqLmfbHdcoke6Y5SfiAjVUw/5/ZKSF1XFjU7hR/sTA9cUOfm3AkAKAnzaUWx3pKxXiKZtFqukm3cdgYV84EWcqR3ut7J91PJGTUk70e5AGVIVDHuG9yIg+HAPka8cA4sTwf2Fv0hl";
        // String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCE9/u7/iYRBKvLkcdMcz81uLMAmtc//BusF2gP54gJGFJyNALrUS2x1sEEfFl9TaxvRFOBu3bBjbyPLKYXQhkMYGYiywr0c7QOzAtp40yZ8csq7wt+idyXuUddO4jbgHfA9NtdFJ1/Q+PoXb8oy+pUkwLotNYwqtyy8LrVRmALGwIDAQAB";
        // // 签名
        // String data = "{\"b\": \"测试\", \"a\":\"RSA\"}";
        // String sign = sign(Base64.decodeBase64(data), privateKey);
        // System.out.println("sign => " + sign);
        //
        // boolean verify = verify(Base64.decodeBase64(data), publicKey, sign);
        // System.out.println(verify);
        // String s = encrypt(data, publicKey);
        // System.out.println("加密后：" + s);
        // String java = decrypt(s, privateKey);
        // System.out.println("解密后：" + java);


        // String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJ9d8zOCDiblFEuDa9ytgEU3iwGETVW1bWwGRfELnC0JFo5m/SS52T0IhB9Tpz54RppkpSfKDEdZ1Kp3BREITQgqAtyiVcX5Eea7+uX3vsV+NGD2kCQGDnPTk98cOpaqQiypfSJFpI/fUFRk6C3Bp9uIG/Z0G9EEx2rTe3Lirw5BAgMBAAECgYBtt2Ga4XvavTWWs1jL6cr4XD/gAHS5gBlgGIWIaMTRoIMd8Ltw0F5GDZngc1gdwvJgks+9L/X6HVczMJOVYVCeKwuBo6JcgK64lhh58wcOlMVcUSydIN4QXbUcWmPnqTsZ1xErTQSdF6ybbNbP02Kf9VL0c/2SEnFx+hlQv4ZoPQJBAM/HxXGisWmA4WMU6WSw5zN78ms85v9nAUb16eHTxEA+Gopn/0kZVdZG7DOudcC9B3h8Q+pDlZ+aY3JL0246K/cCQQDEWfD4W5xmJsr7Jf/G/i00iqMsEoaosBN8EbuyoTqGAauazqdRREv906y8Z43m+UcdyUyyvev+qya2ohDkz1mHAkBhJ5QXEm/KWU0KO1j2kBFLbYVox01r1wot2AbIZXC6aU+XsBEaaRJN41PGxqigusKnf9Nx0rA/tL0TUIlIXUL5AkEAkbima8uhkPZtYmLbJtXwurPBUa4WHg8/Bq8qe/HIOzf2IZgI+PkU5LY51kGMQMT0EJkawPTOtlxTCOvSWd3A9QJBALYU/fjwJsgA9z6/+yV60JX0TmqrS6HBP4MZ72ICDmgfrL7Fy/q+mmMWn952wxA05eqssl7mnXX0PHekdmrd9JU=";
        // String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfXfMzgg4m5RRLg2vcrYBFN4sBhE1VtW1sBkXxC5wtCRaOZv0kudk9CIQfU6c+eEaaZKUnygxHWdSqdwURCE0IKgLcolXF+RHmu/rl977FfjRg9pAkBg5z05PfHDqWqkIsqX0iRaSP31BUZOgtwafbiBv2dBvRBMdq03ty4q8OQQIDAQAB";
        // String data = encryptedDataOnJava("aaa", publicKey);
        // String java = decryptDataOnJava(data, privateKey);
        // System.out.println(java);
    }
}